from src.utils.time_tool import get_china_time
from sys import audit

from src.api.ArticleRouter.resource import ptool
from src.init.init_db import db
from src.model.AritcleModel import ArticleModel
from src.model.ALikeModel import ALikeModel
from src.model.UserModel import UserModel
from src.model.TypeModel import TypeModel
from src.utils.comment_tool import CommentTool
from src.utils.picture_tool import PictureTool
from src.utils.type_tool import TypeTool
from src.utils.aview_tool import AViewTool

from src.utils.llm_tool import (
    sort_articles_by_keyword_interest_new,
    sort_articles_by_interest_new,
)

import difflib
from typing import List, Dict

ctool = CommentTool()
ttool = TypeTool()
ptool = PictureTool()
atool = AViewTool()


class ArticleTool:

    def init(self, uid: int):
        """初始化一篇文章，如果用户没有未提交的文章则创建一篇。

        Args:
            uid (int): 用户ID。

        Returns:
            dict: 包含文章ID (aid) 的字典。
        """
        article = ArticleModel.query.filter_by(uid=uid, audit=False).first()
        if article is not None:
            return {"aid": article.aid}
        self.uid = uid
        article = ArticleModel(uid=uid, title="wait_commit", audit=False)
        db.session.add(article)
        db.session.commit()
        return {"aid": article.aid}

    def update_article(
        self, aid: int, title: str = "标题", content: str = "内容", tid: int = 1
    ):
        """更新一篇文章的标题、内容和标签。

        Args:
            aid (int): 文章ID。
            title (str, optional): 新的文章标题。 Defaults to "标题".
            content (str, optional): 新的文章内容。 Defaults to "内容".
            tid (int, optional): 新的文章标签ID。 Defaults to 1.

        Returns:
            dict: 包含操作成功与否信息的字典。
        """
        article = ArticleModel.query.filter_by(aid=aid).first()
        if article is None:
            return {"success": False, "err": "文章不存在！"}
        if TypeModel.query.filter_by(tid=tid).first() is None:
            return {"success": False, "err": "标签不存在！"}
        article.title = title
        article.content = content
        article.tid = tid
        article.audit = True
        article.createtime = get_china_time()
        db.session.commit()
        return {"success": True}

    def delete_article(self, aid: int, uid: int):
        """删除一篇文章。

        管理员可以删除任何文章，普通用户只能删除自己的文章。

        Args:
            aid (int): 文章ID。
            uid (int): 用户ID。

        Returns:
            dict: 包含操作成功与否信息的字典。
        """
        user = UserModel.query.filter_by(uid=uid).first()
        article = ArticleModel.query.filter_by(aid=aid).first()
        if user is None:
            return {"success": False, "err": "用户不存在！"}
        # 当前用户是管理员用户
        if user.role != 0:
            if article is None:
                return {"success": False, "err": "文章不存在！"}
            ptool.delete_picture(article.aid)
            db.session.delete(article)
            db.session.commit()
            return {"success": True}
        # 当前用户为普通用户
        article = ArticleModel.query.filter_by(aid=aid, uid=uid).first()
        if article is None:
            return {"success": False, "err": "您没有权限！"}
        ptool.delete_picture(article.aid)
        db.session.delete(article)
        db.session.commit()
        return {"success": True}

    def filter_list(self, tids: list, articles: ArticleModel) -> dict:
        """根据标签ID过滤文章列表。

        Args:
            tids (list): 需要过滤掉的标签ID列表。
            articles (ArticleModel): 待过滤的文章模型列表。

        Returns:
            dict: 包含过滤后文章数量和文章列表的字典。
        """
        count = 0
        datalist = []

        for article in articles:
            if article.tid in tids or article.audit is False:
                continue
            count += 1
            temDic = article.profile
            temData = {
                "aid": article.aid,
                "articleTitle": article.title,
                "views": article.view,
                "summary": temDic["summary"],
                "tags": temDic["tags"][:4],
                "createtime": article.createtime,
            }
            datalist.append(temData)

        data = {"count": count, "datalist": datalist}
        return data

    def get_list(self, tids: list, articles: ArticleModel) -> dict:
        """根据标签ID获取文章列表。

        Args:
            tids (list): 需要查找的标签ID列表。
            articles (ArticleModel): 待查询的文章模型列表。

        Returns:
            dict: 包含查询结果数量和文章列表的字典。
        """
        count = 0
        datalist = []
        for article in articles:
            if article.tid not in tids or article.audit is False:
                continue
            count += 1

            tid = TypeModel.query.filter_by(name="已经被领取的任务").first().tid
            if article.tid == tid:
                tmp_data = {
                    "aid": article.aid,
                    "articleTitle": article.title,
                    "views": article.view,
                    "state": "ack",
                }
            else:
                tmp_data = {
                    "aid": article.aid,
                    "articleTitle": article.title,
                    "views": article.view,
                    "state": "wait",
                }
            datalist.append(tmp_data)
        data = {"count": count, "datalist": datalist}
        return data

    def get_by_type(self, articles: ArticleModel, types: str) -> dict:
        """根据文章类型获取文章数据。

        Args:
            articles (ArticleModel): 文章模型列表。
            types (str): 查找的文章类型 ("article", "notice", "task")。

        Returns:
            dict: 包含查询结果的字典。
        """
        data = None
        if types == "article":
            # 获取tid对应的type为公告和任务的文章
            # 暂未完成 tids为公告、任务
            tids = ttool.list_task_tags() + ttool.list_announce_tags()
            data = self.filter_list(tids, articles)
        elif types == "notice":
            # 获取tid对应的type为公告的文章
            # 暂未完成 tids为公告
            tids = ttool.list_announce_tags()
            data = self.get_list(tids, articles)

        elif types == "task":
            # 获取tid对应的type为任务的文章
            # 暂未完成 tids为任务
            tids = ttool.list_task_tags()
            data = self.get_list(tids, articles)

        return data

    def get_article(self, article: ArticleModel, uid: int) -> dict:
        """获取单篇文章的详细信息。

        包括文章内容、评论、点赞等信息。

        Args:
            article (ArticleModel): 文章模型。
            uid (int): 当前用户ID。

        Returns:
            dict: 包含文章详细信息的字典。
        """
        data = {
            "aid": article.aid,
            "articleTitle": article.title,
            "views": article.view + 1,
            "createTime": article.createtime,
            "content": article.content,
        }

        # time 格式转换
        data["createTime"] = data["createTime"].strftime("%Y年%m月%d日 %H:%M:%S")
        # name 查找
        name = UserModel.query.filter_by(uid=article.uid).first().name
        data["name"] = name
        # like 查找
        like = False
        if uid != 0:
            like = (
                True
                if ALikeModel.query.filter_by(aid=article.aid, uid=uid).first()
                is not None
                else False
            )
        data["like"] = like
        # alike 查找
        alikes = ALikeModel.query.filter_by(aid=article.aid).count()
        data["alikes"] = alikes
        # comment 查找
        commentList = ctool.get_comment(article.aid, uid)
        data["commentList"] = commentList

        return data

    def filter_list_keyword(
        self,
        tids: list,
        articles: List[ArticleModel],
        keyword: List[str],
        threshold: float = 0.01,
    ):
        """根据关键词过滤文章列表。

        Args:
            tids (list): 要排除的标签ID列表。
            articles (List[ArticleModel]): 待过滤的文章列表。
            keyword (List[str]): 关键词列表。
            threshold (float, optional): 相似度阈值。 Defaults to 0.01.

        Returns:
            dict: 包含过滤后文章数量和文章列表的字典。
        """
        valid_list = [article for article in articles if article.audit is True]
        if not valid_list:
            return []

        # 将关键词合并为一个字符串
        keyword_str = " ".join(keyword).lower()

        # 计算每篇文章标题与关键词的相似度分数
        scored_articles = []
        for article in valid_list:
            title = article.title.lower()
            score = difflib.SequenceMatcher(None, title, keyword_str).ratio()
            if score >= threshold:
                scored_articles.append((score, article))

        # 可选：按相似度排序（如果需要）
        scored_articles.sort(key=lambda x: x[0], reverse=True)

        # 构造返回数据
        dataList = []
        for score, article in scored_articles:
            temData = {
                "aid": article.aid,
                "articleTitle": article.title,
                "views": article.view,
                "summary": article.profile["summary"],
                "tags": article.profile["tags"][:4],
                "createtime": article.createtime,
            }
            dataList.append(temData)

        return {"count": len(dataList), "datalist": dataList}

    def filter_list_interest_new(
        self,
        tids: list,
        articles: list[ArticleModel],
        userProfile: dict,
        version: str = "professional",
    ):
        """根据用户兴趣推荐文章 (新版)。

        Args:
            tids (list): 要排除的标签ID列表。
            articles (list[ArticleModel]): 待推荐的文章列表。
            userProfile (dict): 用户画像。
            version (str, optional): 使用的模型版本。 Defaults to "professional".

        Returns:
            tuple: 包含处理流程和推荐数据的元组。
        """

        validList = []
        for article in articles:
            if article.audit is False:
                continue
            validList.append(article)

        if not validList:
            return None, {}

        # 正确解包返回的元组
        total_process, final_recommendations, article_distances = sort_articles_by_interest_new(
            validList,
            userProfile,
            version,
            5,
            0.1,
        )

        if not total_process or not final_recommendations:
            return None, {}

        recommendation_data = []
        # 遍历列表，保持顺序，并构建前端所需的数据结构
        for process_dict in final_recommendations:
            new_process_dict = {}
            for process_name, keywords_data in process_dict.items():
                new_keywords_data = {}
                for keyword, articles_list in keywords_data.items():
                    formatted_articles = []
                    for rec_item in articles_list:
                        article = rec_item["article"]
                        personalized_summary = rec_item["summary"]

                        temDic = article.profile
                        temData = {
                            "aid": article.aid,
                            "articleTitle": article.title,
                            "views": article.view,
                            "summary": temDic.get("summary", "暂无摘要"),
                            "personalized_summary": personalized_summary,
                            "tags": temDic.get("tags", [])[:4],
                            "createtime": article.createtime,
                            "recommend": article_distances[article.aid] * 2.5 + 2.5,
                        }
                        formatted_articles.append(temData)

                    if formatted_articles:
                        new_keywords_data[keyword] = formatted_articles

                if new_keywords_data:
                    new_process_dict[process_name] = new_keywords_data

            if new_process_dict:
                recommendation_data.append(new_process_dict)

        return total_process, recommendation_data

    def filter_list_keywords_interest_new(
        self,
        tids: list,
        articles: list[ArticleModel],
        userProfile: dict,
        keyword: List[str],
    ):
        """根据关键词和用户兴趣推荐文章 (新版)。

        Args:
            tids (list): 要排除的标签ID列表。
            articles (list[ArticleModel]): 待推荐的文章列表。
            userProfile (dict): 用户画像。
            keyword (List[str]): 关键词列表。

        Returns:
            dict: 包含推荐文章数量和文章列表的字典。
        """
        validList = []
        for article in articles:
            if article.audit is False:
                continue
            validList.append(article)

        if not validList:
            return {"count": 0, "datalist": []}

        categorized_recommendations, article_distances = (
            sort_articles_by_keyword_interest_new(
                validList, userProfile, keyword, 10, 0.1
            )
        )

        dataList = []
        count = 0
        for className in categorized_recommendations:
            for validArticle in categorized_recommendations[className]:
                count += 1
                temDic = validArticle.profile
                temData = {
                    "aid": validArticle.aid,
                    "articleTitle": validArticle.title,
                    "views": validArticle.view,
                    "summary": temDic["summary"],
                    "recommend": article_distances[validArticle.aid] * 2.5 + 2.5,
                    "tags": temDic["tags"][:4],
                    "createtime": validArticle.createtime,
                    "class": className,
                }
                dataList.append(temData)

        return {"count": count, "datalist": dataList}
